package rendering;

import java.util.List;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;

import scene.Scene;
import util.CgPanel;

public class RaycastingRenderer implements RenderListener{
	
	private Scene scene;
	private List<RenderThread> threads;
	private List<Bucket> buckets;
	private final CgPanel panel;
	private long startTime;
	
	public final int NB_BUCKETS_X = 10;
	public final int NB_BUCKETS_Y = 10;
	
	
	public RaycastingRenderer(Scene scene, CgPanel panel){
		this.scene = scene;
		threads = new CopyOnWriteArrayList<RenderThread>();
		buckets = new Vector<Bucket>(NB_BUCKETS_X * NB_BUCKETS_Y);
		this.panel = panel;
	}
	
	public void render(int nbOfthreads){
		scene.getCurrentCamera().setNx(panel.getWidth());
		scene.getCurrentCamera().setNy(panel.getHeight());
		int xBucketWidth = panel.getWidth() / NB_BUCKETS_X,
			yBucketWidth = panel.getHeight() / NB_BUCKETS_Y;
		//Stop previously running rendering threads
		
		for(RenderThread t : threads){
			if(t.isAlive()){
				t.stopRendering();
			}
		}
		threads.clear();
		buckets.clear();
		for(int i = 0; i < NB_BUCKETS_X; i++){
			for(int j = 0; j  < NB_BUCKETS_Y; j++){
				buckets.add(new Bucket(i * xBucketWidth, (i+1) * xBucketWidth, j * yBucketWidth, (j+1) * yBucketWidth));
			}
		}
		//start rendering again
		startTime = System.currentTimeMillis();
		for(int i = 0; i < nbOfthreads; i++){
			if(!buckets.isEmpty()){
				Bucket bucketToRender = buckets.get(0);
				buckets.remove(0);
				RenderThread t = new RenderThread(panel, bucketToRender);
				threads.add(t);
				t.addRenderListener(this);
				t.start();
			}
			
		}
		//wait for them to join
//		for(int i = 0; i < nbOfthreads; i++){
//			try {
//				threads.get(i).join();
//			} catch (InterruptedException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
//		}
		
	}

	@Override
	public void doneRendering(RenderThread rt) {
		threads.remove(rt);
		if(!buckets.isEmpty()){
			Bucket bucketToRender = buckets.get(0);
			buckets.remove(0);
			RenderThread t = new RenderThread(panel, bucketToRender);
			threads.add(t);
			t.addRenderListener(this);
			t.start();
		}
		else if(threads.isEmpty()){
			System.out.println("Finished rendering.");
			System.out.println("Render time: " + (System.currentTimeMillis() - startTime) + "ms.");
		}
	}
}
